package com.woniuxy.user.filter;


import com.woniuxy.commons.request.ResponseResult;
import com.woniuxy.commons.request.StateCode;
import com.woniuxy.user.util.ResponseWrapper;
import lombok.extern.slf4j.Slf4j;
import org.codehaus.jackson.map.ObjectMapper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.Map;
import java.util.concurrent.TimeUnit;


@Slf4j
@Component
public class LoginFilter implements Filter {
    @Value("${oauth2.refresh_token_expire}")
    private int REFRESH_TOKEN_EXPIRE;
    
    @Resource
    private RedisTemplate<String,Object> redisTemplate;
    
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        Filter.super.init(filterConfig);
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest)servletRequest;
        HttpServletResponse response = (HttpServletResponse)servletResponse;
        ResponseWrapper responseWrapper = new ResponseWrapper(response);

        log.info("获取到客户端id、密码");
        String authorization = request.getHeader("Authorization");
        log.info("解码数据");
        byte[] bytes = Base64.getDecoder().decode(authorization.startsWith("Basic")?authorization.split(" ")[1]:authorization);
        String ap = new String(bytes, StandardCharsets.UTF_8);
        String client_id = ap.split(":")[0];
        String client_secret = ap.split(":")[1];
        log.info("客户端信息：" + client_id + "," + client_secret);

        log.info("获取grant_type区别是认证还是刷新token");
        String grantType = request.getParameter("grant_type");

        if ("password".equals(grantType)){
            log.info("判断结果为<登录>请求，直接放行");
            filterChain.doFilter(servletRequest, responseWrapper);

            String responseData = responseWrapper.getResponseData("utf-8");
            log.info("解析认证结果得到：" + responseData);

            Map<String,Object> data = new ObjectMapper().readValue(responseData,Map.class);
            log.info("将结果转换为map：" + data.toString());

            //判断是否成功
            if (data.containsKey("access_token")){
                log.info("登录成功");
                // 返回登录结果
                response.getWriter().write(responseData);

                data.put("client_id", client_id);
                data.put("client_secret",client_secret);
                log.info("封装用户信息，存入Redis：" + data.toString());
                // 存redis
                redisTemplate.opsForHash().putAll((String) data.get("refresh_token"),data);
                //
                redisTemplate.expire((String) data.get("refresh_token"),REFRESH_TOKEN_EXPIRE, TimeUnit.SECONDS);
                log.info("存入Redis成功");
            } else if((int)data.get("code") == 500){
                ResponseResult<Boolean> responseResult = new ResponseResult<>(StateCode.LOGIN_FAIL, "账号密码错误", false);
                String result = new ObjectMapper().writeValueAsString(responseResult);
                response.setContentType("application/json;charset=utf-8");
                response.getWriter().write(result);
            } else if((int)data.get("code") == 705){
                ResponseResult<Boolean> responseResult = new ResponseResult<>(StateCode.ACCOUNT_LOCKED, "账号已被锁定", false);
                String result = new ObjectMapper().writeValueAsString(responseResult);
                response.setContentType("application/json;charset=utf-8");
                response.getWriter().write(result);
            }
            return;
        }
        // 刷新token
        log.info("<刷新token>请求");
        //
        log.info("获取到原来的refresh_token");
        String refreshToken = request.getParameter("refresh_token");
        log.info("refresh_token:" + refreshToken);
        // 放行
        filterChain.doFilter(servletRequest, responseWrapper);
        // 解析结果
        log.info("解析刷新结果");
        String responseData = responseWrapper.getResponseData("utf-8");

        // 响应结果
        response.getWriter().write(responseData);
        //
        if (responseData.contains("access_token")){
            log.info("刷新token成功，将新的token信息存入Redis");
            // 重新设置redis中的数据
            Map<String, Object> map = new ObjectMapper().readValue(responseData,Map.class);
            map.put("client_id", client_id);
            map.put("client_secret",client_secret);

            redisTemplate.opsForHash().putAll((String) map.get("refresh_token"),map);
            redisTemplate.expire((String) map.get("refresh_token"),REFRESH_TOKEN_EXPIRE,TimeUnit.SECONDS);
            // 删除原来的数据
            redisTemplate.delete(refreshToken);
            log.info("更新Redis成功");
        }
    }

    @Override
    public void destroy() {
        Filter.super.destroy();
    }
}